/*
 *  hlfs_open.c
 *  Kanghua <kanghua151@msn.com> (C) 2011
 *  Updated by Harry Wei <harryxiyou@gmail.com>
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <glib.h>
#include "hlfs.h"
#include "comm_define.h"
#include "misc.h"
#include "logger.h"


/*
 * load_latest_inode: load the lastest inode structure for ctrl.
 * @param ctrl: the global control for our FS.
 * @return: if successful return 0, else return -1.
 */

static int load_latest_inode(struct hlfs_ctrl *ctrl)
{
   int ret = 0; 
   gchar *segfile_name = build_segfile_name(ctrl->last_segno);
   bs_file_t file = ctrl->storage->bs_file_open(ctrl->storage,segfile_name,BS_READONLY); 
   if(file==NULL){
      g_message("1 ---------> can not open segment file %s\n",segfile_name);
      goto out2; 
   }

   uint64_t inode_pos = ctrl->last_offset - 
                        sizeof(struct inode_map_entry) -
                        sizeof(struct inode);

   g_message("inode pos  %llu\n",inode_pos);
   if(sizeof(struct inode) != 
            ctrl->storage->bs_file_pread(ctrl->storage,file,&ctrl->inode,
                 sizeof(struct inode),
                 inode_pos)){
       g_message("can not read inode from %s\n",segfile_name);
       ret = -1;
       goto out1;
    }
out1:
    ctrl->storage->bs_file_close(ctrl->storage,file);
out2:
    g_free(segfile_name);
    return ret;
}

/*
 * hlfs_open: open a file.
 * @param ctrl: the global control.
 * @param flag: the flag for open operation, flag == 0
 *        readonly and flag == 1 writable.
 * @return: if successful return 0, else return -1.
 */

int hlfs_open(struct hlfs_ctrl *ctrl, int flag)
{
        if (ctrl==NULL ||(flag != 0 && flag != 1)) { /* check the parameters */
                g_message("error params :falg %d\n",flag);
                return -1;
        }
        int ret;
        g_message("inode no %llu , inode address %llu \n", ctrl->imap_entry.inode_no, ctrl->imap_entry.inode_addr);
        if (ctrl->imap_entry.inode_no == 0 && 
                ctrl->imap_entry.inode_addr == 0) { /* no inode condition */
                g_message("empty filesystem %s\n", ctrl->sb.fsname);
                if (flag == 0) {
                        g_message("must create it with writeable flag \n");
                        return -1;
                }
                g_message("create new fs inode !\n");
                ctrl->inode.length = 0;
                ctrl->inode.mtime = get_current_time();
                ctrl->inode.ctime = get_current_time();
                ctrl->inode.atime = get_current_time();
        } else { /* exist inode */
                g_message("open exist fs %s\n", ctrl->sb.fsname);
                if (0 != load_latest_inode(ctrl)) { /* get the lastest inode structure */ 
                        g_message("fail to load inode !\n");
                        return -1; 
                }
                g_message("inode 's length:%llu\n",ctrl->inode.length);
        }
        g_message("append log with only inode !\n");
        int size = append_inode(ctrl); /* append new log */
        if (size < 0) {
                g_message("fail to append log with inode ! %d\n",size);
                return -1;
        }
        ctrl->last_offset += size;
        return 0;
}


